bitkeeper revision 1.1599 (429b828aL4XKwdaPjLGObI37F4hwiw)
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Mon, 30 May 2005 21:15:54 +0000 (21:15 +0000)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Mon, 30 May 2005 21:15:54 +0000 (21:15 +0000)
By default do not enable local APIC if disabled by the BIOS. This
matches Linux behaviour and ought to improve stability on buggy
hardware/firmware (laptops in particular). As in Linux, you can
forcibly enable the APIC with 'lapic' command-line option, or
forcibly ignore it with 'nolapic'.
Signed-off-by: Keir Fraser <keir@xensource.com>
docs/src/user.tex
xen/arch/x86/apic.c
xen/arch/x86/genapic/probe.c
xen/arch/x86/setup.c

index 594ef59135a03f58147b1bc10f42c2044897838e..e2988ec2a06692beeb3140ac9c35fc822fb3579f 100644 (file)
@@ -1770,14 +1770,25 @@ editing \path{grub.conf}.
  Select the CPU scheduler Xen should use.  The current
  possibilities are `bvt' (default), `atropos' and `rrobin'. 
  For more information see Section~\ref{s:sched}. 
-\end{description} 
 
-In addition, the following platform-specific options may be specified
-on the Xen command line. Since domain 0 shares responsibility for
-booting the platform, Xen will automatically propagate these options
-to its command line.
+\item [apic\_verbosity=debug,verbose ]
+ Print more detailed information about local APIC and IOAPIC configuration.
+
+\item [lapic ]
+ Force use of local APIC even when left disabled by uniprocessor BIOS.
+
+\item [nolapic ]
+ Ignore local APIC in a uniprocessor system, even if enabled by the BIOS.
+
+\item [apic=bigsmp,default,es7000,summit ]
+ Specify NUMA platform. This can usually be probed automatically.
 
-These options are taken from Linux's command-line syntax with
+\end{description} 
+
+In addition, the following options may be specified on the Xen command
+line. Since domain 0 shares responsibility for booting the platform,
+Xen will automatically propagate these options to its command
+line. These options are taken from Linux's command-line syntax with
 unchanged semantics.
 
 \begin{description}
@@ -1792,9 +1803,6 @@ unchanged semantics.
  Instruct Xen (and domain 0) to ignore any IOAPICs that are present in
  the system, and instead continue to use the legacy PIC.
 
-\item [apic=debug,verbose ]
- Print more detailed information about local APIC and IOAPIC configuration.
-
 \end{description} 
 
 \section{XenLinux Boot Options}
index 985736507496a60781e1d399cb0ad23e09d36a19..684a1805409f02fd997a6a4d4c866e757838241c 100644 (file)
@@ -99,6 +99,13 @@ void clear_local_APIC(void)
         apic_write_around(APIC_LVTPC, v | APIC_LVT_MASKED);
     }
 
+/* lets not touch this if we didn't frob it */
+#ifdef CONFIG_X86_MCE_P4THERMAL
+    if (maxlvt >= 5) {
+        v = apic_read(APIC_LVTTHMR);
+        apic_write_around(APIC_LVTTHMR, v | APIC_LVT_MASKED);
+    }
+#endif
     /*
      * Clean APIC state for other OSs:
      */
@@ -110,6 +117,10 @@ void clear_local_APIC(void)
     if (maxlvt >= 4)
         apic_write_around(APIC_LVTPC, APIC_LVT_MASKED);
 
+#ifdef CONFIG_X86_MCE_P4THERMAL
+    if (maxlvt >= 5)
+        apic_write_around(APIC_LVTTHMR, APIC_LVT_MASKED);
+#endif
     v = GET_APIC_VERSION(apic_read(APIC_LVR));
     if (APIC_INTEGRATED(v)) {  /* !82489DX */
         if (maxlvt > 3)        /* Due to Pentium errata 3AP and 11AP. */
@@ -134,6 +145,7 @@ void __init connect_bsp_APIC(void)
         outb(0x70, 0x22);
         outb(0x01, 0x23);
     }
+    enable_apic_mode();
 }
 
 void disconnect_bsp_APIC(void)
@@ -448,20 +460,45 @@ void __init setup_local_APIC (void)
  * Original code written by Keir Fraser.
  */
 
+/*
+ * Knob to control our willingness to enable the local APIC.
+ */
+int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */
+
+static void __init lapic_disable(char *str)
+{
+    enable_local_apic = -1;
+    clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
+}
+custom_param("nolapic", lapic_disable);
+
+static void __init lapic_enable(char *str)
+{
+    enable_local_apic = 1;
+}
+custom_param("lapic", lapic_enable);
+
 static void __init apic_set_verbosity(char *str)
 {
     if (strcmp("debug", str) == 0)
         apic_verbosity = APIC_DEBUG;
     else if (strcmp("verbose", str) == 0)
         apic_verbosity = APIC_VERBOSE;
+    else
+        printk(KERN_WARNING "APIC Verbosity level %s not recognised"
+               " use apic_verbosity=verbose or apic_verbosity=debug", str);
 }
-custom_param("apic", apic_set_verbosity);
+custom_param("apic_verbosity", apic_set_verbosity);
 
 static int __init detect_init_APIC (void)
 {
     u32 h, l, features;
     extern void get_cpu_vendor(struct cpuinfo_x86*);
 
+    /* Disabled by kernel option? */
+    if (enable_local_apic < 0)
+        return -1;
+
     /* Workaround for us being called before identify_cpu(). */
     get_cpu_vendor(&boot_cpu_data);
 
@@ -481,6 +518,15 @@ static int __init detect_init_APIC (void)
     }
 
     if (!cpu_has_apic) {
+        /*
+         * Over-ride BIOS and try to enable the local
+         * APIC only if "lapic" specified.
+         */
+        if (enable_local_apic <= 0) {
+            printk("Local APIC disabled by BIOS -- "
+                   "you can enable it with \"lapic\"\n");
+            return -1;
+        }
         /*
          * Some BIOSes disable the local APIC in the
          * APIC_BASE MSR. This can only be done in
@@ -951,6 +997,9 @@ asmlinkage void smp_error_interrupt(struct cpu_user_regs *regs)
  */
 int __init APIC_init_uniprocessor (void)
 {
+    if (enable_local_apic < 0)
+        clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
+
     if (!smp_found_config && !cpu_has_apic)
         return -1;
 
index 9645f46654ca8019e0ad498e414b933bb922778e..a3a94fe753e61e5f4862a8613e96419f2d1f3449 100644 (file)
@@ -19,7 +19,7 @@ extern struct genapic apic_bigsmp;
 extern struct genapic apic_es7000;
 extern struct genapic apic_default;
 
-struct genapic *genapic = &apic_default;
+struct genapic *genapic;
 
 struct genapic *apic_probe[] __initdata = { 
        &apic_summit,
@@ -29,38 +29,28 @@ struct genapic *apic_probe[] __initdata = {
        NULL,
 };
 
-void __init generic_apic_probe(char *command_line) 
+static void __init genapic_apic_force(char *str)
+{
+       int i;
+       for (i = 0; apic_probe[i]; i++)
+               if (!strcmp(apic_probe[i]->name, str))
+                       genapic = apic_probe[i];
+}
+custom_param("apic", genapic_apic_force);
+
+void __init generic_apic_probe(void) 
 { 
-       char *s;
        int i;
-       int changed = 0;
+       int changed = (genapic != NULL);
 
-       s = strstr(command_line, "apic=");
-       if (s && (s == command_line || isspace(s[-1]))) { 
-               char *p = strchr(s, ' '), old; 
-               if (!p)
-                       p = strchr(s, '\0'); 
-               old = *p; 
-               *p = 0; 
-               for (i = 0; !changed && apic_probe[i]; i++) {
-                       if (!strcmp(apic_probe[i]->name, s+5)) { 
-                               changed = 1;
-                               genapic = apic_probe[i];
-                       }
-               }
-               if (!changed)
-                       printk(KERN_ERR "Unknown genapic `%s' specified.\n", s);
-               *p = old;
-       } 
        for (i = 0; !changed && apic_probe[i]; i++) { 
                if (apic_probe[i]->probe()) {
                        changed = 1;
                        genapic = apic_probe[i]; 
                } 
        }
-       /* Not visible without early console */ 
        if (!changed) 
-               panic("Didn't find an APIC driver"); 
+               genapic = &apic_default;
 
        printk(KERN_INFO "Using APIC driver %s\n", genapic->name);
 } 
index 2d16e56a5289c31fec8b8d8aae0084d54d48887e..d1d89ef4a3506c90abf7e4c8786c65a0c20670c1 100644 (file)
@@ -21,7 +21,7 @@
 #include <asm/e820.h>
 
 extern void dmi_scan_machine(void);
-extern void generic_apic_probe(char *);
+extern void generic_apic_probe(void);
 
 /*
  * opt_xenheap_megabytes: Size of Xen heap in megabytes, excluding the
@@ -67,8 +67,6 @@ boolean_param("acpi_skip_timer_override", acpi_skip_timer_override);
 extern int skip_ioapic_setup;
 boolean_param("noapic", skip_ioapic_setup);
 
-static char *xen_cmdline;
-
 int early_boot = 1;
 
 int ht_per_core = 1;
@@ -179,8 +177,7 @@ static void __init start_of_day(void)
 
     dmi_scan_machine();
 
-    if ( xen_cmdline != NULL )
-        generic_apic_probe(xen_cmdline);
+    generic_apic_probe();
 
     acpi_boot_table_init();
     acpi_boot_init();
@@ -251,10 +248,7 @@ void __init __start_xen(multiboot_info_t *mbi)
 
     /* Parse the command-line options. */
     if ( (mbi->flags & MBI_CMDLINE) && (mbi->cmdline != 0) )
-    {
-        xen_cmdline = __va(mbi->cmdline);
-        cmdline_parse(xen_cmdline);
-    }
+        cmdline_parse(__va(mbi->cmdline));
 
     /* Must do this early -- e.g., spinlocks rely on get_current(). */
     set_current(&idle0_exec_domain);
@@ -436,13 +430,6 @@ void __init __start_xen(multiboot_info_t *mbi)
             strcat(cmdline, " acpi=");
             strcat(cmdline, acpi_param);
         }
-        if ( !strstr(cmdline, "apic=") )
-        {
-            if ( apic_verbosity == APIC_VERBOSE )
-                strcat(cmdline, " apic=verbose");
-            else if ( apic_verbosity == APIC_DEBUG )
-                strcat(cmdline, " apic=debug");
-        }
     }
 
     /*